package com.barneyx.mshinfoplatform.web.common;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.barneyx.mshinfoplatform.common.ExResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;

@RestController
@RequestMapping("/api/upload/oss/")
public class AliyunOssController {
    @Resource
    private OSS ossClient;
    @Value("${alibaba.cloud.access-key}")
    private String acccessKey;
    @Value("${alibaba.cloud.secret-key}")
    private String secretKey;
    @Value("${alibaba.cloud.oss.endpoint}")
    private String endpoint;
    @Value("${alibaba.cloud.oss.bucket-name}")
    private String bucketName;


    @Value("${alibaba.cloud.sts.sts-accesskey}")
    private String StsAccessKey;
    @Value("${alibaba.cloud.sts.sts-secretkey}")
    private String StsSecretKey;
    @Value("${alibaba.cloud.sts.sts-endpoint}")
    private String StsEndpoint;
    @Value("${alibaba.cloud.sts.sts-role-arn}")
    private String StsRoleArn;
    @Value("${alibaba.cloud.sts.sts-session-name}")
    private String StsSessionName;

    @GetMapping("/getPolicy")
    public ExResult getPolicy() {
        String host = StrUtil.concat(true, "https://", bucketName, ".", endpoint);
        String dir = "hmproject/" + LocalDate.now().getYear() + "/";
        long expireTime = 100;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000; //过期时间 100 秒
        Date expiration = new Date(expireEndTime);
        // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
        String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = ossClient.calculatePostSignature(postPolicy);


        return ExResult.ofSuccess(MapUtil.builder(new HashMap<String, Object>())
                .put("policy", MapUtil.builder(new HashMap<String, Object>())
                        .put("OSSAccessKeyId", acccessKey)
                        .put("policy", encodedPolicy)
                        .put("signature", postSignature)
                        .put("expire", String.valueOf(expireEndTime / 1000))
                        .put("bucket", bucketName)
                        .put("endpoint", endpoint)
                        .put("AccessKeySecret", secretKey)
                        .build())
                .put("exfileinfo", MapUtil.builder(new HashMap<String, Object>())
                        .put("dir", dir)
                        .put("host", host)
                        .put("rename", IdUtil.getSnowflake(1, 1).nextIdStr())
                        .build())
                .build()
        );
    }


    @GetMapping("/ststoken")
    public ExResult getStsToken() throws ClientException {
        String regionId = "";
        String roleArn = StsRoleArn;
        String roleSessionName = StsSessionName;
        Long durationSeconds = 3600L;
//        String ENDPOINT = "sts.aliyuncs.com";	sts.cn-shanghai.aliyuncs.com
        String ENDPOINT = StsEndpoint;
        String AccessKeyID = StsAccessKey;
        String AccessKeySecret = StsSecretKey;
        String policy = "{\n" +
                "  \"Version\": \"1\",\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Action\": [\n" +
                "        \"oss:PutObject\",\n" +
                "        \"oss:InitiateMultipartUpload\",\n" +
                "        \"oss:UploadPart\",\n" +
                "        \"oss:UploadPartCopy\",\n" +
                "        \"oss:CompleteMultipartUpload\",\n" +
                "        \"oss:AbortMultipartUpload\",\n" +
                "        \"oss:ListMultipartUploads\",\n" +
                "        \"oss:ListParts\"\n" +
                "      ],\n" +
                "      \"Resource\": [\n" +
                "        \"acs:oss:*:*:hmproject/*\"\n" +
                "      ]\n" +
                "    }\n" +
                "  ]\n" +
                "}\n";


        DefaultProfile.addEndpoint(regionId, "Sts", ENDPOINT);
        IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyID, AccessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        final AssumeRoleRequest request = new AssumeRoleRequest();
        request.setSysMethod(MethodType.POST);
        request.setMethod(MethodType.POST);
        request.setRoleArn(roleArn);
        request.setRoleSessionName(roleSessionName);
        request.setPolicy(policy);
        request.setDurationSeconds(durationSeconds);
        final AssumeRoleResponse response = client.getAcsResponse(request);


        String file_name = IdUtil.fastSimpleUUID();
        Date current_Dt = new Date();
        return ExResult.ofSuccess(MapUtil.builder(new HashMap<String, Object>())
                .put("sts", response.getCredentials())
                .put("ossconfig", MapUtil.builder(new HashMap<String, Object>())
                        .put("bucketName", bucketName)
                        .put("endpoint", endpoint)
                        .put("dir", "/" + DateUtil.year(current_Dt) + "/" + (DateUtil.month(current_Dt) + 1) + "/" + file_name)
                        .put("filename", file_name)
                        .build())
                .build());
    }
}
